/*
 * CSessionEntity.cpp
 *
 *  Created on: 2011-9-7
 *      Author: stargui
 */

#include "CSessionEntity.h"
#include "CSessionManager.h"


CSessionEntity::CSessionEntity()
{
	passiveMode		= true;
	markedIndex		= 0x80000000;
	sessionHandle		= -1;
	sessionstatus		= 0;
	sessionlevel		= 0;
	loginstyle			= 0;
	memset(&logintime,0,sizeof(datetime_t));
	clientip.clear();
	username.clear();
	password.clear();
	_task.clear();

	_operation.clear();
	_operation[MODULE_MEDIASTREAM"_"MEDIAREMOTEPLAYBACK_REQUEST]		= boost::bind(&CSessionEntity::OnRequestRemotePlayback,this,_1);//Զ��ͬ���ط�
	_operation[MODULE_MEDIASTREAM"_"MEDIA_CONTROLREMOTEPLAYBACK]		= boost::bind(&CSessionEntity::OnControlRemotePlayback,this,_1);//Զ��ͬ���طſ���


}

CSessionEntity::~CSessionEntity()
{
	CPSelectUtils::mSleep(50);//��������������Դ��ȫ�ͷ�
	std::map<unsigned int, CStreamLayer*> ::iterator it;
	for(it = _task.begin();it != _task.end();it++)
	{
		if(it->second)
		{
			//assert(NULL != it->second);
			delete it->second;
		}
		it->second	= NULL;
	}
	_task.clear();
}

void CSessionEntity::SetTaskCallback(boost::function<bool(unsigned int,unsigned int, Json::Value &,int,void*)> callback)
{
	_sessionCallback = callback;
}

int CSessionEntity::InsertSessionTask(unsigned int taskindex,int taskHandle, std::string taskName,void *_threadid)
{
	if(SearchSessionTask(taskName,taskindex))
	{
		DEBUG_WARNING("-------------task----is-----exsist---getpid:%d----\n",getpid());
		return -2;
	}

	CPSocketUtils::SetSocketBuffer(taskHandle, 128 * 1024, 250 * 1024);
	CPSocketUtils::SetSockNoDelay(taskHandle);

	CStreamLayer	*streamlayer		= NULL;
	streamlayer						= new CStreamLayer();
	streamlayer->taskHandle 			= taskHandle;
	streamlayer->taskindex			= taskindex;
	streamlayer->taskName 			= taskName;
	streamlayer->source				= markedIndex;
	streamlayer->passiveMode			= passiveMode;
	streamlayer->_threadid			= _threadid;
	streamlayer->status				= 0;
	//streamlayer->_handleRealstream 	= _handleRealstream;
	streamlayer->username			= username;
	streamlayer->password			= password;
	//taskindex���豸�˵�Ψһ��ʶ��pc��Ψһ��ʶtaskname���Ӧ
	//�����������ý��״̬�ش���session��������֪ͨ�ϲ�
	_task[taskindex]					= streamlayer;
	_task[taskindex]->SetTaskSessionCallback(boost::bind(&CSessionEntity::TaskCallback,this,_1,_2,_3,_4));
	_task[taskindex]->Start();
	DEBUG_WARNING("-the markedinde[%02X] add new task's taskname is [%s] task size: %d,taskindex:[%d] ",markedIndex,taskName.c_str(), _task.size(),taskindex);
	return 0;
}

//�󶨻ش�
bool CSessionEntity::TaskCallback(unsigned int source,unsigned int taskindex, Json::Value &response,int type)
{
	 _sessionCallback(source,taskindex,response,type,_task[taskindex]->_threadid);
	 return true;
}

bool CSessionEntity::RemoveSessionTask(unsigned int taskindex)
{
	if (_task.find(taskindex) != _task.end())
	{
		DEBUG_WARNING("+++++++++delete++++taskindex:[%d]+++++--size:%d----------------\n",taskindex,_task.size());
		delete _task[taskindex];
		_task[taskindex]			= NULL;
		_task.erase(taskindex);
	}
	return true;
}

bool CSessionEntity::ActiveReleaseTask()
{
	std::map<unsigned int, CStreamLayer*>::iterator nextit;
	std::map<unsigned int, CStreamLayer*>::iterator it;
	int			activehandle		= -1;
	for(it = _task.begin();it != _task.end();)
	{
		if(it->second && (1 == it->second->status))
		{
			nextit				= it;
			nextit++;
			activehandle		= it->second->taskHandle;
			if(it->second)
			{
				delete	it->second;
			}
			it->second			= NULL;
			_task.erase(it);
			//��������ͷ�socket��֤ÿ�������е�socketΨһ
			CPSocketUtils::CloseSocket(activehandle);
			it					= nextit;
		}
		else
		{
			it++;
		}
	}
	return true;
}

void CSessionEntity::QuerySessionTask(unsigned int taskindex,int& status)
{
	if (_task.find(taskindex) != _task.end())
	{
		if(_task[taskindex] && (1 ==_task[taskindex]->status))
		{
			status	= 1;
		}
	}
}

bool CSessionEntity::HandleSessionRequest(Json::Value &request)
{
	std::map<std::string, boost::function<bool(Json::Value &)> >::iterator it;
	std::string operation = request[MODULE].asString() +"_"+ request[OPERATION].asString();
	if ((it = _operation.find(operation)) != _operation.end())//根据申请的指令解析是否未已经处理的指令
	{
		return it->second(request);
	}
	return false;
}

bool CSessionEntity::HandleSessionTask(int taskHandle, CProtocolFactory *packet)
{
	return true;
}

bool CSessionEntity::SearchSessionTask(std::string taskName,  unsigned int &taskindex)
{
	std::map<unsigned int, CStreamLayer*> ::iterator it;
	for(it = _task.begin();it != _task.end();it++)//在处理媒体指令前需要先验证是否有媒体链路，因为媒体指令处理后需要媒体链路传输数据
	{
		if(it->second && (it->second->taskName == taskName))
		{
			if(it->second->status)
			{
				return false;
			}
			break;
		}
	}
	if(it == _task.end())
	{
		return false;
	}
	//taskHandle	= it->first;
	taskindex		= it->second->taskindex;
	return true;
}


bool CSessionEntity::OnRequestRemotePlayback(Json::Value & request)
{
	unsigned int taskindex = 0;
	if (SearchSessionTask(request[PARAMETER][MEDIASTREAM_STREAMNAME].asString(), taskindex))
	{
		if(_task[taskindex])
		{//处理指令
			_task[taskindex]->RequestRemotePlayback(request);
		}
	}
	else if (passiveMode)
	{
		Json::Value response;
		response[MODULE]						= request[MODULE];
		response[SESSION] 					= request[SESSION];
		response[OPERATION] 					= request[OPERATION];
		response[RESPONSE][ERRORCODE] 		= NOTASK;
		response[RESPONSE][ERRORCAUSE] 		= EP_CN_NOTASK;
		response[RESPONSE][MEDIASTREAM_STREAMNAME]	= request[PARAMETER][MEDIASTREAM_STREAMNAME];
		_sessionCallback(markedIndex,taskindex,response,0,NULL);
	}

	return true;
}

bool CSessionEntity::OnControlRemotePlayback(Json::Value & request)
{
	unsigned int taskindex = 0;

	if (SearchSessionTask(request[PARAMETER][MEDIASTREAM_STREAMNAME].asString(), taskindex))
	{
		if(_task[taskindex])
		{
			_task[taskindex]->ControlRemotePlayback(request);
		}
		return true;
	}
	Json::Value response;
	response[MODULE]						= request[MODULE];
	response[SESSION] 					= request[SESSION];
	response[OPERATION] 					= request[OPERATION];
	response[RESPONSE][ERRORCODE]	 	= NOTASK;
	response[RESPONSE][ERRORCAUSE] 		= EP_CN_NOTASK;
	response[RESPONSE][MEDIASTREAM_STREAMNAME]	= request[PARAMETER][MEDIASTREAM_STREAMNAME];
	_sessionCallback(markedIndex,taskindex,response,0,NULL  );
	return true;
}





